打包项目:使用 webpack & swc-loader 打包
NestJS 原生支持 webpack 作为打包工具。通过配置 webpack,可以将整个项目(包括所有模块和依赖)打包成单文件输出。本节介绍如何在 NestJS 中集成 webpack + swc-loader,实现从 TS 源码到单文件的完整打包流程。
NestJS 启用 webpack 打包
1. 修改 nest-cli.json
{
"compiler": {
"webpack": true
}
}
json
2. 安装 webpack 依赖
pnpm add -D webpack webpack-cli swc-loader @swc/core
bash
webpack 配置文件
在项目根目录创建 webpack.config.js:
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/main.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
// 开启缓存,加速后续构建
cache: {
type: 'filesystem',
},
resolve: {
extensions: ['.ts', '.js'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/, // 关键:排除 node_modules 大幅提升构建速度
use: {
loader: 'swc-loader',
// 使用默认的 .swcrc 配置文件
// options: {} // 或自定义选项覆盖 .swcrc
},
},
],
},
}
javascript
swc-loader 自定义配置
如果需要在 webpack 配置中覆盖 .swcrc 的设置,可以通过 options 传递:
const fs = require('fs')
function loadSwcConfig() {
const configPath = path.resolve(__dirname, '.swcrc')
const raw = fs.readFileSync(configPath, 'utf8')
const config = JSON.parse(raw)
delete config.$schema // 移除 schema 字段
return config
}
module.exports = {
// ...其他配置
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'swc-loader',
options: {
...loadSwcConfig(),
// 覆盖特定选项
minify: true,
},
},
},
],
},
}
javascript
exclude 的重要性
最初不配置 exclude: /node_modules/ 时,webpack 会将所有 node_modules 中的依赖也打包进来,构建时间可能高达 30 秒。加上 exclude 后:
| 配置 | 构建时间 | 输出大小 |
|---|---|---|
| 不排除 node_modules | ~30s | 较大 |
| 排除 node_modules | ~3s | ~542KB(压缩后) |
排除 node_modules 的原因是:dependencies 中的包已经被各自的作者打包过了,我们只需要将它们安装到目标环境即可,无需重复打包。
构建与验证
# 构建
nest build
# 查看输出
ls dist/
# bundle.js
# 运行打包后的文件
node dist/bundle.js
bash
打包后的 bundle.js 特点:
- 代码经过压缩和混淆(由
.swcrc中的 minify/mangle 配置控制) - 所有项目源码被合并为单文件
- 文件大小约 542KB(压缩后)
构建速度对比
| 工具 | 构建时间 | 说明 |
|---|---|---|
| SWC 编译 | ~160ms | 仅做语法转换,保持目录结构 |
| webpack + swc-loader | ~3s | 解析模块、应用插件、最终打包 |
| webpack(不含 exclude) | ~30s | 包含了 node_modules 的打包 |
为什么 webpack 比 SWC 慢
SWC 是纯粹的编译器,只负责语法转换(TS -> JS),不关心模块解析、依赖图构建等打包相关工作。而 webpack 的工作流程包括:
- 解析(Resolve):从入口文件开始,递归解析所有 import/require
- 构建(Build):对每个模块应用 loader 转换
- 打包(Bundle):将所有模块合并为输出文件
这也是 Vite 在开发环境使用 esbuild(编译器),生产环境使用 Rollup(打包器)的设计思路。
使用建议
| 场景 | 推荐工具 |
|---|---|
| 仅需语法转换,保持目录结构 | SWC(nest build) |
| 需要单文件输出,方便部署 | webpack + swc-loader 或 Rollup + SWC |
| Docker 镜像部署 | SWC 编译 + COPY node_modules(推荐) |
| Serverless / Lambda 部署 | webpack 或 Rollup 打包单文件 |
还原 SWC 编译模式
测试完成后,将 nest-cli.json 中的 webpack 配置关闭:
{
"compiler": {
"webpack": false,
"builder": "swc"
}
}
json
小结
本节介绍了 webpack + swc-loader 在 NestJS 中的配置和使用:
- 通过
nest-cli.json中webpack: true启用 webpack 打包 swc-loader复用.swcrc配置,避免重复配置 decorators、mangle 等选项exclude: /node_modules/是提升构建速度的关键- webpack 输出单文件
bundle.js,适合需要单文件部署的场景 - 纯编译场景(如 Docker 部署)直接使用 SWC 编译即可,无需 webpack
下一节将使用 Rollup 替代 webpack 进行对比,评估两者的构建效率和便利性。
↑